package com.example.chuzhou.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.chuzhou.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.message.BasicNameValuePair;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.example.chuzhou.constans.CommonConstans.*;

@SuppressWarnings("all")
@Api(description = "滁州大屏接口")
@RestController
@RequestMapping("api/V1/cz")
@CrossOrigin(origins = "*")
@Slf4j
public class loginController {


    @Value(value = "${ca.driveUrl}")
    String path;

    @Autowired
    RedisUtils redisUtils;

    @SuppressWarnings("rawtypes")
    @Resource(name = "redisStringTemplate")
    private RedisTemplate redisTemplate;

    //5.1
    @ApiOperation("用户名+密码登录")
    @PostMapping("login")
    public String login(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "desc of param", required = true) @RequestBody Map map) throws Exception {

        map.put("client_id", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("client_secret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
        map.put("grant_type", "password");
        //密文密码 解密
        pwdDecrypt(map);
        String url = IP + "/oauth/oauth/token";
        String str = HttpRequest.httpPostData(url, appendMap(map), request);
        String authorization = "";
        if (StringUtils.isNotBlank(str)) {
            JSONObject json = JSONObject.parseObject(str);
            JSONObject data = JSONObject.parseObject(json.getString("data"));
            if (null == data) return str;
            String expires_in = data.getString("expires_in");
            log.info(json.toJSONString());
            // 已经登录 则不作处理
            authorization = "Bearer " + data.getString("access_token");
            if (!checkIsLogin(request, response, data, expires_in)) return str;
            String sessionId = getSessionId();
            CookieUtil.setCookie(response, SESSION_KEY, sessionId, Integer.parseInt(expires_in));
            redisUtils.set(authorization, sessionId, Integer.parseInt(expires_in));
            redisUtils.set("ZHCS_" + sessionId, data.toString(), Integer.parseInt(expires_in));
        }
//        log.info(str);
        if (StringUtils.isNotBlank(authorization)) {
            String userInfo = HttpRequest.httpPostData(IP + "/oauth/userInfo", "", authorization, request);
            LogUtil.sendLog(request, "用户名+密码登录", OPERTYPE_LOGIN, map.get("grant_type"), url, buildUserId(userInfo));
        }
        return str;
    }

    //5.13 获取登录验证码
    @ApiOperation("发送短信验证码")
    @PostMapping("sendSms")
    public String sendSms(HttpServletRequest request, @RequestBody Map map) throws Exception {
        log.info("发送短信验证码开始");
        map.put("clientId", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("clientSecret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
        //密文密码 解密
        pwdDecrypt(map);
        String url = IP + "/oauth/getMobileCaptcha";
        String str = HttpRequest.httpPostData(url, appendMap(map), request);
        log.info(appendMap(map));
        log.info(str);
        log.info("发送短信验证码结束");
//        LogUtil.sendLog(request, "发送短信验证码", OPERTYPE_ADD, appendMap(map), url, "");
        return str;
    }

    //5.14
    @ApiOperation("用户名+密码+短信验证码登录")
    @PostMapping("smsLogin")
    public String smsLogin(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "desc of param", required = true) @RequestBody Map map) throws Exception {
        log.info("用户名+密码+短信验证码登录开始");
        map.put("client_id", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("client_secret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
        map.put("grant_type", "captcha");
        //密文密码 解密
        pwdDecrypt(map);
        String url = IP + "/oauth/oauth/token";
        String str = HttpRequest.httpPostData(url, appendMap(map), request);
        String authorization = "";
        if (StringUtils.isNotBlank(str)) {
            JSONObject json = JSONObject.parseObject(str);
            JSONObject data = JSONObject.parseObject(json.getString("data"));
            if (null == data) return str;
            String expires_in = data.getString("expires_in");
            log.info(json.toJSONString());
            // 已经登录 则不作处理
            authorization = "Bearer " + data.getString("access_token");
            if (!checkIsLogin(request, response, data, expires_in)) return str;
            String sessionId = getSessionId();
            CookieUtil.setCookie(response, SESSION_KEY, sessionId, Integer.parseInt(expires_in));
            redisUtils.set(authorization, sessionId, Integer.parseInt(expires_in));
            redisUtils.set("ZHCS_" + sessionId, data.toString(), Integer.parseInt(expires_in));
        }
        log.info("用户名+密码+短信验证码登录结束");
        if (StringUtils.isNotBlank(authorization)) {
            String userInfo = HttpRequest.httpPostData(IP + "/oauth/userInfo", "", authorization, request);
            LogUtil.sendLog(request, "用户名+密码+短信验证码登录", OPERTYPE_LOGIN, map.get("grant_type"), url, buildUserId(userInfo));
        }
//        log.info(str);
        return str;
    }

    //5.9
    @ApiOperation("查询是否需要修改密码")
    @PostMapping("searchNeedChangeSec")
    public String searchNeedChangeSec(HttpServletRequest request) throws Exception {
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
        String url = IP + "/oauth/searchNeedChangeSec";
        String str = HttpRequest.httpPostData(url, "", Authorization, request);
        LogUtil.sendLog(request, "查询是否需要修改密码", OPERTYPE_QUERY, "", url, getUserId(request));
        return str;
    }

    //5.2
    @ApiOperation("获取授权码")
    @PostMapping("getAuth")
    public String get(HttpServletRequest request, HttpServletResponse response, @RequestBody Map map) throws Exception {
//        map.put("clientId","94e3d6f1-100a-405a-8c04-910874639e39");
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
//        String Authorization = map.get("token_type")+" "+map.get("access_token");
        //验证该用户是否有子系统访问权限
        boolean flag = checkUserAccess(map, Authorization, request);
        if (!flag) return "用户没有此子系统访问权限，请联系管理员！";
        String url = IP + "/oauth/auth";
        String str = HttpRequest.httpPostData(url, appendMap(map), Authorization, request);
        LogUtil.sendLog(request, "获取授权码", OPERTYPE_QUERY, appendMap(map), url, getUserId(request));
        try {
            refreshToken(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    //5.3
    @ApiOperation("获取子系统列表")
    @PostMapping("getSystemList")
    public String getSystemList(HttpServletRequest request, HttpServletResponse response, @RequestBody Map map) throws Exception {

        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
        String url = IP + "/oauth/systemList";
        String str = HttpRequest.httpPostData(url, appendMap(map), Authorization, request);
        LogUtil.sendLog(request, "获取子系统列表", OPERTYPE_QUERY, appendMap(map), url, getUserId(request));
        try {
            refreshToken(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    //5.4
    @ApiOperation("获取授权码token")
    @PostMapping("getoken")
    public String getoken(HttpServletRequest request, @RequestBody Map map) throws Exception {
        map.put("grant_type", "authorization_code");
        map.put("client_id", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("client_secret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
//        log.info(map.toString());
        String url = IP + "/oauth/oauth/token";
        String str = HttpRequest.httpPostData(url, appendMap(map), Authorization, request);
//        log.info(str);
        LogUtil.sendLog(request, "获取授权码token", OPERTYPE_QUERY, appendMap(map), url, getUserId(request));
        return str;
    }

    private String getUserId(HttpServletRequest request) throws Exception {
        String userInfo = getUserInfo(request, null);
        return buildUserId(userInfo);
    }

    private String buildUserId(String userInfo) {
        if (StringUtils.isBlank(userInfo)) return "";
        JSONObject json = JSONObject.parseObject(userInfo);
        JSONObject data = JSONObject.parseObject(json.getString("data"));
        if (StringUtils.isBlank(String.valueOf(data))) return "";
        return data.getString("id");
    }

    //5.6
    @ApiOperation("获取用户信息")
    @PostMapping("getUserInfo")
    public String getUserInfo(HttpServletRequest request, @RequestBody Map map) throws Exception {
        log.info("获取用户信息开始");
        log.info("CookieUtil.getCookie(request, SESSION_KEY) " + CookieUtil.getCookie(request, SESSION_KEY));
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        log.info("data.toJSONString() " + data.toJSONString());
        String Authorization = "Bearer " + data.getString("access_token");
//        log.info(map.toString());
        String url = IP + "/oauth/userInfo";
        String str = HttpRequest.httpPostData(url, appendMap(map), Authorization, request);
//        log.info(str);
//        LogUtil.sendLog(request, "获取用户信息", OPERTYPE_QUERY, appendMap(map), url, buildUserId(str));
        log.info("获取用户信息结束");
        return str;
    }

    //5.8
    @ApiOperation("修改密码")
    @PostMapping("changSec")
    public String changSec(HttpServletRequest request, @RequestBody Map map) throws Exception {
        map.put("clientId", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("clientSecret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
//        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
//        String Authorization = "Bearer " + data.getString("access_token");
        pwdDecrypt(map);
        String keyIndex = AESUtil.generateShortUuid();
        map.put("password", AESUtil.encrypt(map.get("password").toString(), keyIndex));
        map.put("key_index", keyIndex);
//        log.info(map.toString());
        String url = IP + "/oauth/changSec";
        String str = HttpRequest.httpPostData(url, appendMap(map), "", request);
//        log.info(str);
        LogUtil.sendLog(request, "修改密码", OPERTYPE_UPDATE, "", url, "");
        return str;
    }

    //5.5
    @ApiOperation("刷新token")
    @PostMapping("refreshToken")
    public String refreshToken(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject tokenData = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + tokenData.getString("access_token");
        Map<String, Object> map = new HashMap<>();
        map.put("refresh_token", tokenData.getString("refresh_token"));
        map.put("grant_type", "refresh_token");
        map.put("client_id", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("client_secret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");

        String url = IP + "/oauth/oauth/token";
        String str = HttpRequest.httpPostData(url, appendMap(map), "", request);
        String authorization = "";
        if (StringUtils.isNotBlank(str)) {
            JSONObject json = JSONObject.parseObject(str);
            JSONObject data = JSONObject.parseObject(json.getString("data"));
            if (null == data) return str;
            String expires_in = data.getString("expires_in");
            log.info(json.toJSONString());
            // 已经登录 则不作处理
            authorization = "Bearer " + data.getString("access_token");
            if (!checkIsLogin(request, response, data, expires_in)) return str;
            String sessionId = CookieUtil.getCookie(request, SESSION_KEY);
            CookieUtil.setCookie(response, SESSION_KEY, sessionId, Integer.parseInt(expires_in));
            redisUtils.set(authorization, sessionId, Integer.parseInt(expires_in));
            redisUtils.set("ZHCS_" + sessionId, data.toString(), Integer.parseInt(expires_in));
            redisUtils.del(Authorization);
        }
        if (StringUtils.isNotBlank(authorization)) {
            String userInfo = HttpRequest.httpPostData(IP + "/oauth/userInfo", "", authorization, request);
            LogUtil.sendLog(request, "刷新token", OPERTYPE_QUERY, map.get("grant_type"), url, buildUserId(userInfo));
        }
        return str;
    }

    //5.7
    @ApiOperation("登出")
    @PostMapping("logout")
    public String logout(HttpServletRequest request, @RequestBody Map map) throws Exception {
        log.info("门户登出开始");
        String url = IP + "/oauth/logout";
        LogUtil.sendLog(request, "门户登出", OPERTYPE_LOGOUT, appendMap(map), url, getUserId(request));
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
        log.info("Authorization：" + Authorization);
//        log.info(map.toString());
        String str = HttpRequest.httpPostData(url, appendMap(map), Authorization, request);
//        log.info(str);
//        redisTemplate.delete("Bearer " + data.getString("access_token"));
//        redisTemplate.delete("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY));
//        request.getSession().setAttribute("token",str);
        log.info("门户登出结束");
        return str;
    }

    //5.12
    @ApiOperation("UKey登录接口")
    @PostMapping("catoken")
    public String catoken(HttpServletRequest request, HttpServletResponse response, @RequestBody Map map) throws Exception {
        log.info("UKey登录接口开始");
        map.put("client_id", "94e3d6f1-100a-405a-8c04-910874639e39");
        map.put("client_secret", "f4d98bc6-4229-47e8-9a35-2de7d6fb6985");
        map.put("grant_type", "ca");
        log.info(JSONObject.toJSONString(map));
        String url = IP + "/oauth/oauth/catoken";
        String str = HttpRequest.httpPostData(url, appendMap1(map));
        String authorization = "";
        if (StringUtils.isNotBlank(str)) {
            JSONObject json = JSONObject.parseObject(str);
            if (!json.getBoolean("success")) return str;
            JSONObject data = JSONObject.parseObject(json.getString("data"));
            String expires_in = data.getString("expires_in");
            log.info(json.toJSONString());
            // 已经登录 则不作处理
            authorization = "Bearer " + data.getString("access_token");
            if (!checkIsLogin(request, response, data, expires_in)) return str;
            String sessionId = getSessionId();
            CookieUtil.setCookie(response, SESSION_KEY, sessionId, Integer.parseInt(expires_in));
            redisUtils.set(authorization, sessionId, Integer.parseInt(expires_in));
            redisUtils.set("ZHCS_" + sessionId, data.toString(), Integer.parseInt(expires_in));
        }
        log.info(str);
        log.info("UKey登录接口结束");
//        log.info(str);
        if (StringUtils.isNotBlank(authorization)) {
            String userInfo = HttpRequest.httpPostData(IP + "/oauth/userInfo", "", authorization, request);
            LogUtil.sendLog(request, "UKey登录", OPERTYPE_LOGIN, map.get("grant_type"), url, buildUserId(userInfo));
        }
        return str;
    }


    //6.1.2.1
    @ApiOperation("获取站内信接口")
    @PostMapping("msgList")
    public String msgList(HttpServletRequest request, @RequestBody Map map) throws Exception {
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
        log.info("获取站内信接口 map.toString() " + map.toString());
        String url = IP + "/oauth/msg-server/msgList";
        String str = HttpRequest.httpPostDataJson(url, JSONObject.toJSONString(map), Authorization, request);
        log.info("获取站内信接口 str " + str);
        LogUtil.sendLog(request, "获取站内信", OPERTYPE_QUERY, JSONObject.toJSONString(map), url, getUserId(request));
        return str;
    }

    //6.1.2.1
    @ApiOperation("批量获取用户")
    @PostMapping("getUserList")
    public String getUserList(HttpServletRequest request, @RequestBody Map map) throws Exception {
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_540bb3a8635d43a2bfde0838424c8198") + "");
        String Authorization = data.getString("access_token");
        String url = IP + "/oauth/userSync";
        String str = HttpRequest.httpPostData(url, JSONObject.toJSONString(map), Authorization, request);
        log.info("批量获取用户 str " + str);
//        LogUtil.sendLog(request, "获取站内信", OPERTYPE_QUERY, JSONObject.toJSONString(map), url, getUserId(request));
        return str;
    }


    //6.2.2.2
    @ApiOperation("站内信状态变更接口")
    @PostMapping("changeMsgStatus")
    public String changeMsgStatus(HttpServletRequest request, @RequestBody Map map) throws Exception {
        JSONObject data = JSONObject.parseObject(redisTemplate.opsForValue().get("ZHCS_" + CookieUtil.getCookie(request, SESSION_KEY)) + "");
        String Authorization = "Bearer " + data.getString("access_token");
        String url = IP + "/oauth/msg-server/changeMsgStatus/" + String.valueOf(map.get("id"));
        String str = HttpRequest.httpPostDataJson(url, "", Authorization, request);
        log.info("站内信状态变更接口 str " + str);
        LogUtil.sendLog(request, "站内信状态变更", OPERTYPE_UPDATE, appendMap(map), url, getUserId(request));
        return str;
//        return id;
    }


    @GetMapping(value = "/downloadCADrive", produces = {"application/json;"})
    @ApiOperation("下载CA驱动")
    @ResponseBody
    public void downloadCADrive(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //通过路径得到一个输入流
//        String path = "/root/chuzhou/ca/mPlugin_SKF_Setup.exe";
        FileInputStream fis = new FileInputStream(path);
        //创建字节输出流
        ServletOutputStream os = response.getOutputStream();
        //得到要下载的文件名
//        String filename = path.substring(path.lastIndexOf("\\") + 1);
        String filename = path.substring(path.lastIndexOf("/") + 1);
        //设置文件名的编码
        filename = URLEncoder.encode(filename, "utf-8");//将不安全的文件名改为utf-8的形式
        //告知客户端要下载文件
        response.setHeader("content-disposition", "attachment;filename=" + filename);
//        response.setHeader("content-type", "image/jpeg");
        response.setContentType("application/octet-stream;charset=UTF-8");
        //执行输出操作
        int len = 1;
        byte[] b = new byte[1024];
        while ((len = fis.read(b)) != -1) {
            os.write(b);
        }
        os.close();
        fis.close();
    }


    private boolean checkUserAccess(Map map, String authorization, HttpServletRequest request) {
        try {
            AtomicBoolean flag = new AtomicBoolean(false);
            String clientId = map.get("clientId").toString();
            String url = IP + "/oauth/systemList";
            String str = HttpRequest.httpPostData(url, appendMap(map), authorization, request);
            if (StringUtils.isNotBlank(str)) {
                JSONObject json = JSONObject.parseObject(str);
                JSONArray data = json.getJSONArray("data");
                data.forEach(e -> {
                    Object o = JSONObject.toJSONString(e);
                    JSONArray list = ((JSONObject) e).getJSONArray("list");
                    list.forEach(e1 -> {
                        if (((JSONObject) e1).getString("clientId").equals(clientId)) {
                            flag.set(((JSONObject) e1).getString("status").equals("1"));
                        }
                    });
                });
            }
            return flag.get();
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

    /**
     * http请求参数拼接
     *
     * @param data
     * @return
     */
    public static String appendMap(Map data) {
        StringBuffer retStr = new StringBuffer("");
        StringBuffer sb = new StringBuffer();
        if (data != null && data.size() != 0) {
            Iterator i = data.entrySet().iterator();

            while (i.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry) i.next();
                sb.append("&").append((String) entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue()));
            }
            String param = sb.substring(1);
            retStr.append(param);
        }
        return retStr.toString();
    }

    /**
     * http请求参数拼接
     *
     * @param data
     * @return
     */
    public static List<BasicNameValuePair> appendMap1(Map data) {
        List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
        if (data != null && data.size() != 0) {
            Iterator i = data.entrySet().iterator();

            while (i.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry) i.next();
                pairList.add(new BasicNameValuePair((String) entry.getKey(), entry.getValue()));
            }
        }
        return pairList;
    }

    /**
     * 创建sessionId
     *
     * @return
     */
    public String getSessionId() {
        return UUID.randomUUID().toString().replace("-", "");
    }


    /**
     * 判断该账号是否已经登录
     *
     * @param request
     * @param data
     * @return true 新增 redis; false 不作处理
     */
    public boolean checkIsLogin(HttpServletRequest request,
                                HttpServletResponse response,
                                JSONObject data,
                                String expires_in
    ) {
        Object key = redisTemplate.opsForValue().get("Bearer " + data.getString("access_token"));
        if (key != null) {
            //重新刷新 token时效
            // 该账号已经登录 不作处理
            CookieUtil.setCookie(response, SESSION_KEY, (String) key, Integer.parseInt(expires_in));
            return false;
        } else {
            // 未登录存储
            return true;
        }
    }

    /**
     * 密文密码 解密
     */
    public void pwdDecrypt(Map map) {
        try {
            if (map.get("password") != null) map.put("password", SM2Util.decrypt2(map.get("password").toString()));
            if (map.get("oldpwd") != null) map.put("oldpwd", SM2Util.decrypt2(map.get("oldpwd").toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
